Sveobuhvatan vodič za spajanje i pridruživanje DataFrameova u Python Pandasu, pokrivajući strategije kao što su unutarnje, vanjsko, lijevo i desno spajanje s praktičnim primjerima.
Python Pandas spajanje: Ovladavanje strategijama spajanja DataFrameova za analizu podataka
Manipulacija podacima ključan je aspekt analize podataka, a biblioteka Pandas u Pythonu pruža moćne alate za tu svrhu. Među tim alatima, spajanje i pridruživanje DataFrameova su bitne operacije za kombiniranje skupova podataka na temelju zajedničkih stupaca ili indeksa. Ovaj sveobuhvatni vodič istražuje različite strategije spajanja DataFrameova u Pandasu, opremajući vas znanjem za učinkovito kombiniranje i analizu podataka iz različitih izvora.
Razumijevanje spajanja i pridruživanja DataFrameova
Spajanje i pridruživanje DataFrameova uključuje kombiniranje dva ili više DataFramea u jedan DataFrame na temelju zajedničkog stupca ili indeksa. Glavna razlika između `merge` i `join` je u tome što je `merge` funkcija biblioteke Pandas i obično spaja DataFrameove po stupcima, dok je `join` metoda DataFramea koja prvenstveno spaja DataFrameove po indeksima, iako se može koristiti i sa stupcima.
Ključni pojmovi
- DataFrameovi: Dvodimenzionalne označene podatkovne strukture sa stupcima potencijalno različitih tipova.
- Zajednički stupci/indeksi: Stupci ili indeksi koji dijele isto ime i tip podataka u različitim DataFrameovima, služeći kao osnova za spajanje/pridruživanje.
- Vrste spajanja: Različite strategije za rukovanje neusklađenim redovima tijekom procesa spajanja/pridruživanja, uključujući unutarnje, vanjsko, lijevo i desno spajanje.
Spajanje DataFrameova s `pd.merge()`
Funkcija `pd.merge()` primarni je alat za spajanje DataFrameova na temelju stupaca. Nudi fleksibilan način kombiniranja podataka na temelju jednog ili više zajedničkih stupaca.
Sintaksa
pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'), copy=True, indicator=False, validate=None)
Parametri
- left: Lijevi DataFrame za spajanje.
- right: Desni DataFrame za spajanje.
- how: Vrsta spajanja koja se izvodi ('inner', 'outer', 'left', 'right'). Zadana vrijednost je 'inner'.
- on: Naziv stupca(a) po kojima se spaja. Moraju se nalaziti u oba DataFramea.
- left_on: Naziv stupca(a) u lijevom DataFrameu koji se koriste kao ključevi za spajanje.
- right_on: Naziv stupca(a) u desnom DataFrameu koji se koriste kao ključevi za spajanje.
- left_index: Ako je True, koristi indeks iz lijevog DataFramea kao ključ(eve) za spajanje.
- right_index: Ako je True, koristi indeks iz desnog DataFramea kao ključ(eve) za spajanje.
- sort: Sortira rezultirajući DataFrame leksikografski po ključevima spajanja. Zadana vrijednost je False.
- suffixes: N-terac string sufiksa koji se primjenjuju na preklapajuće nazive stupaca. Zadana vrijednost je ('_x', '_y').
- copy: Ako je False, izbjegava kopiranje podataka u novi DataFrame gdje je to moguće. Zadana vrijednost je True.
- indicator: Ako je True, dodaje stupac nazvan '_merge' koji ukazuje na izvor svakog reda.
- validate: Provjerava je li spajanje navedenog tipa. "one_to_one", "one_to_many", "many_to_one", "many_to_many".
Objašnjenje vrsta spajanja
Parametar `how` u `pd.merge()` određuje vrstu spajanja koja se izvodi. Različite vrste spajanja na različite načine rukuju neusklađenim redovima.
Unutarnje spajanje (Inner Join)
Unutarnje spajanje vraća samo one redove koji imaju podudarne vrijednosti u oba DataFramea na temelju ključeva spajanja. Redovi s neusklađenim vrijednostima isključeni su iz rezultata.
Primjer:
Uzmimo u obzir dva DataFramea:
import pandas as pd
# DataFrame 1: Customer Orders
df_orders = pd.DataFrame({
'order_id': [1, 2, 3, 4, 5],
'customer_id': [101, 102, 103, 104, 105],
'product_id': [1, 2, 1, 3, 2],
'quantity': [2, 1, 3, 1, 2]
})
# DataFrame 2: Customer Information
df_customers = pd.DataFrame({
'customer_id': [101, 102, 103, 106],
'customer_name': ['Alice', 'Bob', 'Charlie', 'David'],
'country': ['USA', 'Canada', 'UK', 'Australia']
})
# Inner Join
df_inner = pd.merge(df_orders, df_customers, on='customer_id', how='inner')
print(df_inner)
Izlaz:
order_id customer_id product_id quantity customer_name country
0 1 101 1 2 Alice USA
1 2 102 2 1 Bob Canada
2 3 103 1 3 Charlie UK
U ovom primjeru, unutarnje spajanje kombinira DataFrameove `df_orders` i `df_customers` na temelju stupca `customer_id`. U rezultat su uključeni samo kupci koji su izvršili narudžbe. Kupac 'David' (customer_id 106) je isključen jer nema narudžbi.
Vanjsko spajanje (Outer Join / Full Outer Join)
Vanjsko spajanje vraća sve redove iz oba DataFramea, uključujući neusklađene redove. Ako red nema podudaranje u drugom DataFrameu, odgovarajući stupci sadržavat će `NaN` (Not a Number) vrijednosti.
Primjer:
# Outer Join
df_outer = pd.merge(df_orders, df_customers, on='customer_id', how='outer')
print(df_outer)
Izlaz:
order_id customer_id product_id quantity customer_name country
0 1.0 101 1.0 2.0 Alice USA
1 2.0 102 2.0 1.0 Bob Canada
2 3.0 103 1.0 3.0 Charlie UK
3 4.0 104 3.0 1.0 NaN NaN
4 5.0 105 2.0 2.0 NaN NaN
5 NaN 106 NaN NaN David Australia
Vanjsko spajanje uključuje sve kupce i sve narudžbe. Kupci 104 i 105 imaju narudžbe, ali nemaju podatke o kupcima, a kupac 106 ima podatke o kupcu, ali nema narudžbi. Vrijednosti koje nedostaju predstavljene su kao `NaN`.
Lijevo spajanje (Left Join)
Lijevo spajanje vraća sve redove iz lijevog DataFramea i podudarne redove iz desnog DataFramea. Ako red u lijevom DataFrameu nema podudaranje u desnom DataFrameu, odgovarajući stupci iz desnog DataFramea sadržavat će `NaN` vrijednosti.
Primjer:
# Left Join
df_left = pd.merge(df_orders, df_customers, on='customer_id', how='left')
print(df_left)
Izlaz:
order_id customer_id product_id quantity customer_name country
0 1 101 1 2 Alice USA
1 2 102 2 1 Bob Canada
2 3 103 1 3 Charlie UK
3 4 104 3 1 NaN NaN
4 5 105 2 2 NaN NaN
Lijevo spajanje uključuje sve narudžbe iz `df_orders`. Kupci 104 i 105 imaju narudžbe, ali nemaju podatke o kupcima, pa su stupci `customer_name` i `country` za te narudžbe `NaN`.
Desno spajanje (Right Join)
Desno spajanje vraća sve redove iz desnog DataFramea i podudarne redove iz lijevog DataFramea. Ako red u desnom DataFrameu nema podudaranje u lijevom DataFrameu, odgovarajući stupci iz lijevog DataFramea sadržavat će `NaN` vrijednosti.
Primjer:
# Right Join
df_right = pd.merge(df_orders, df_customers, on='customer_id', how='right')
print(df_right)
Izlaz:
order_id customer_id product_id quantity customer_name country
0 1.0 101 1.0 2.0 Alice USA
1 2.0 102 2.0 1.0 Bob Canada
2 3.0 103 1.0 3.0 Charlie UK
3 NaN 106 NaN NaN David Australia
Desno spajanje uključuje sve kupce iz `df_customers`. Kupac 106 ima podatke o kupcu, ali nema narudžbi, pa su stupci `order_id`, `product_id` i `quantity` za tog kupca `NaN`.
Pridruživanje DataFrameova s `df.join()`
Metoda `df.join()` prvenstveno se koristi za pridruživanje DataFrameova na temelju njihovih indeksa. Može se koristiti i za pridruživanje po stupcima, ali je obično praktičnije koristiti `pd.merge()` za spajanja temeljena na stupcima.
Sintaksa
DataFrame.join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False)
Parametri
- other: Drugi DataFrame za pridruživanje.
- on: Naziv stupca po kojem se pridružuje. Mora se proslijediti ako se indeks ne koristi kao ključ za pridruživanje.
- how: Kako rukovati operacijom lijevog i desnog skupa. Zadana vrijednost je 'left'.
- lsuffix: Sufiks koji se koristi iz lijevog DataFramea za nadjačavanje preklapajućih naziva stupaca.
- rsuffix: Sufiks koji se koristi iz desnog DataFramea za nadjačavanje preklapajućih naziva stupaca.
- sort: Sortira rezultirajući DataFrame leksikografski po ključevima spajanja. Zadana vrijednost je False.
Pridruživanje po indeksu
Kada se pridružuje po indeksu, parametar `on` se ne koristi.
Primjer:
# DataFrame 1: Customer Orders with Customer ID as Index
df_orders_index = df_orders.set_index('customer_id')
# DataFrame 2: Customer Information with Customer ID as Index
df_customers_index = df_customers.set_index('customer_id')
# Join on Index (Left Join)
df_join_index = df_orders_index.join(df_customers_index, how='left')
print(df_join_index)
Izlaz:
order_id product_id quantity customer_name country
customer_id
101 1 1 2 Alice USA
102 2 2 1 Bob Canada
103 3 1 3 Charlie UK
104 4 3 1 NaN NaN
105 5 2 2 NaN NaN
U ovom primjeru, metoda `join()` se koristi za izvođenje lijevog spajanja po indeksu (`customer_id`). Rezultat je sličan lijevom spajanju pomoću `pd.merge()`, ali se spajanje temelji na indeksu, a ne na stupcu.
Pridruživanje po stupcu
Za pridruživanje po stupcu pomoću `df.join()`, morate navesti parametar `on`.
Primjer:
# Joining on a column
df_join_column = df_orders.join(df_customers.set_index('customer_id'), on='customer_id', how='left')
print(df_join_column)
Izlaz:
order_id customer_id product_id quantity customer_name country
0 1 101 1 2 Alice USA
1 2 102 2 1 Bob Canada
2 3 103 1 3 Charlie UK
3 4 104 3 1 NaN NaN
4 5 105 2 2 NaN NaN
Ovaj primjer prikazuje pridruživanje `df_orders` s `df_customers` pomoću stupca `customer_id`. Imajte na umu da je `customer_id` postavljen kao indeks u `df_customers` prije izvođenja pridruživanja.
Rukovanje preklapajućim stupcima
Prilikom spajanja ili pridruživanja DataFrameova, često se susreću preklapajući nazivi stupaca (stupci s istim nazivom u oba DataFramea). Pandas nudi parametar `suffixes` u `pd.merge()` te parametre `lsuffix` i `rsuffix` u `df.join()` za rješavanje tih situacija.
Korištenje `suffixes` u `pd.merge()`
Parametar `suffixes` omogućuje vam da navedete sufikse koji će se dodati preklapajućim nazivima stupaca kako bi se razlikovali.
Primjer:
# DataFrame 1: Product Information
df_products1 = pd.DataFrame({
'product_id': [1, 2, 3],
'product_name': ['Product A', 'Product B', 'Product C'],
'price': [10, 20, 15]
})
# DataFrame 2: Product Information (with potentially updated prices)
df_products2 = pd.DataFrame({
'product_id': [1, 2, 4],
'product_name': ['Product A', 'Product B', 'Product D'],
'price': [12, 18, 25]
})
# Merge with suffixes
df_merged_suffixes = pd.merge(df_products1, df_products2, on='product_id', suffixes=('_old', '_new'))
print(df_merged_suffixes)
Izlaz:
product_id product_name_old price_old product_name_new price_new
0 1 Product A 10 Product A 12
1 2 Product B 20 Product B 18
U ovom primjeru, stupci `product_name` i `price` prisutni su u oba DataFramea. Parametar `suffixes` dodaje sufikse `_old` i `_new` kako bi se razlikovali stupci iz lijevog i desnog DataFramea.
Korištenje `lsuffix` i `rsuffix` u `df.join()`
Parametri `lsuffix` i `rsuffix` pružaju sličnu funkcionalnost za `df.join()`. `lsuffix` se dodaje preklapajućim stupcima lijevog DataFramea, a `rsuffix` desnog.
Primjer:
# Join with lsuffix and rsuffix
df_products1_index = df_products1.set_index('product_id')
df_products2_index = df_products2.set_index('product_id')
df_joined_suffixes = df_products1_index.join(df_products2_index, lsuffix='_old', rsuffix='_new', how='outer')
print(df_joined_suffixes)
Izlaz:
product_name_old price_old product_name_new price_new
product_id
1 Product A 10.0 Product A 12.0
2 Product B 20.0 Product B 18.0
3 Product C 15.0 NaN NaN
4 NaN NaN Product D 25.0
Praktični primjeri i slučajevi upotrebe
Spajanje i pridruživanje DataFrameova široko se koristi u različitim scenarijima analize podataka. Evo nekoliko praktičnih primjera:
Kombiniranje podataka o prodaji s informacijama o proizvodima
Uobičajeni slučaj upotrebe je kombiniranje podataka o prodaji s informacijama o proizvodima. Pretpostavimo da imate DataFrame koji sadrži prodajne transakcije i drugi DataFrame koji sadrži detalje o proizvodima. Možete spojiti te DataFrameove kako biste obogatili podatke o prodaji informacijama o proizvodima.
Primjer:
# Sales Transactions Data
df_sales = pd.DataFrame({
'transaction_id': [1, 2, 3, 4, 5],
'product_id': [101, 102, 103, 101, 104],
'quantity': [2, 1, 3, 1, 2],
'sales_date': ['2023-01-15', '2023-02-20', '2023-03-10', '2023-04-05', '2023-05-01']
})
# Product Information Data
df_products = pd.DataFrame({
'product_id': [101, 102, 103, 104],
'product_name': ['Laptop', 'Mouse', 'Keyboard', 'Monitor'],
'category': ['Electronics', 'Electronics', 'Electronics', 'Electronics'],
'price': [1200, 25, 75, 300]
})
# Merge Sales Data with Product Information
df_sales_enriched = pd.merge(df_sales, df_products, on='product_id', how='left')
print(df_sales_enriched)
Izlaz:
transaction_id product_id quantity sales_date product_name category price
0 1 101 2 2023-01-15 Laptop Electronics 1200
1 2 102 1 2023-02-20 Mouse Electronics 25
2 3 103 3 2023-03-10 Keyboard Electronics 75
3 4 101 1 2023-04-05 Laptop Electronics 1200
4 5 104 2 2023-05-01 Monitor Electronics 300
Rezultirajući DataFrame `df_sales_enriched` sadrži prodajne transakcije zajedno s odgovarajućim informacijama o proizvodima, omogućujući detaljniju analizu prodajnih trendova i uspješnosti proizvoda.
Kombiniranje podataka o kupcima s demografskim informacijama
Još jedan uobičajeni slučaj upotrebe je kombiniranje podataka o kupcima s demografskim informacijama. To omogućuje analizu ponašanja kupaca na temelju demografskih čimbenika.
Primjer:
# Customer Data
df_customers = pd.DataFrame({
'customer_id': [1, 2, 3, 4, 5],
'customer_name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
'city': ['New York', 'London', 'Tokyo', 'Sydney', 'Berlin']
})
# Demographic Information Data
df_demographics = pd.DataFrame({
'city': ['New York', 'London', 'Tokyo', 'Sydney', 'Berlin'],
'population': [8419000, 8982000, 13960000, 5312000, 3769000],
'average_income': [75000, 65000, 85000, 90000, 55000]
})
# Merge Customer Data with Demographic Information
df_customer_demographics = pd.merge(df_customers, df_demographics, on='city', how='left')
print(df_customer_demographics)
Izlaz:
customer_id customer_name city population average_income
0 1 Alice New York 8419000 75000
1 2 Bob London 8982000 65000
2 3 Charlie Tokyo 13960000 85000
3 4 David Sydney 5312000 90000
4 5 Eve Berlin 3769000 55000
Rezultirajući DataFrame `df_customer_demographics` sadrži podatke o kupcima zajedno s demografskim informacijama za njihove gradove, omogućujući analizu ponašanja kupaca na temelju demografije grada.
Analiza podataka globalnog lanca opskrbe
Spajanje u Pandasu vrijedno je za analizu podataka globalnog lanca opskrbe, gdje su informacije često raspoređene u više tablica. Na primjer, povezivanje podataka o dobavljačima, informacija o otpremi i prodajnih brojki može otkriti uska grla i optimizirati logistiku.
Primjer:
# Supplier Data
df_suppliers = pd.DataFrame({
'supplier_id': [1, 2, 3],
'supplier_name': ['GlobalTech', 'EuroParts', 'AsiaSource'],
'location': ['Taiwan', 'Germany', 'China']
})
# Shipping Data
df_shipments = pd.DataFrame({
'shipment_id': [101, 102, 103, 104],
'supplier_id': [1, 2, 3, 1],
'destination': ['USA', 'Canada', 'Australia', 'Japan'],
'shipment_date': ['2023-01-10', '2023-02-15', '2023-03-20', '2023-04-25']
})
# Merge Supplier and Shipment Data
df_supply_chain = pd.merge(df_shipments, df_suppliers, on='supplier_id', how='left')
print(df_supply_chain)
Izlaz:
shipment_id supplier_id destination shipment_date supplier_name location
0 101 1 USA 2023-01-10 GlobalTech Taiwan
1 102 2 Canada 2023-02-15 EuroParts Germany
2 103 3 Australia 2023-03-20 AsiaSource China
3 104 1 Japan 2023-04-25 GlobalTech Taiwan
Napredne tehnike spajanja
Spajanje po više stupaca
Možete spojiti DataFrameove na temelju više stupaca prosljeđivanjem liste naziva stupaca parametru `on`.
Primjer:
# DataFrame 1
df1 = pd.DataFrame({
'product_id': [1, 1, 2, 2],
'color': ['red', 'blue', 'red', 'blue'],
'quantity': [10, 15, 20, 25]
})
# DataFrame 2
df2 = pd.DataFrame({
'product_id': [1, 1, 2, 2],
'color': ['red', 'blue', 'red', 'blue'],
'price': [5, 7, 8, 10]
})
# Merge on multiple columns
df_merged_multiple = pd.merge(df1, df2, on=['product_id', 'color'], how='inner')
print(df_merged_multiple)
Izlaz:
product_id color quantity price
0 1 red 10 5
1 1 blue 15 7
2 2 red 20 8
3 2 blue 25 10
Spajanje s različitim nazivima stupaca
Ako stupci za spajanje imaju različite nazive u dva DataFramea, možete koristiti parametre `left_on` i `right_on` kako biste naveli nazive stupaca koji će se koristiti za spajanje.
Primjer:
# DataFrame 1
df1 = pd.DataFrame({
'product_id': [1, 2, 3],
'product_name': ['Product A', 'Product B', 'Product C']
})
# DataFrame 2
df2 = pd.DataFrame({
'id': [1, 2, 4],
'price': [10, 20, 25]
})
# Merge with different column names
df_merged_different = pd.merge(df1, df2, left_on='product_id', right_on='id', how='left')
print(df_merged_different)
Izlaz:
product_id product_name id price
0 1 Product A 1.0 10.0
1 2 Product B 2.0 20.0
2 3 Product C NaN NaN
Korištenje `indicator` za analizu spajanja
Parametar `indicator` u `pd.merge()` dodaje stupac nazvan `_merge` u rezultirajući DataFrame, koji ukazuje na izvor svakog reda. To je korisno za razumijevanje koji su redovi podudarni, a koji nisu.
Primjer:
# Merge with indicator
df_merged_indicator = pd.merge(df_orders, df_customers, on='customer_id', how='outer', indicator=True)
print(df_merged_indicator)
Izlaz:
order_id customer_id product_id quantity customer_name country _merge
0 1.0 101 1.0 2.0 Alice USA both
1 2.0 102 2.0 1.0 Bob Canada both
2 3.0 103 1.0 3.0 Charlie UK both
3 4.0 104 3.0 1.0 NaN NaN left_only
4 5.0 105 2.0 2.0 NaN NaN left_only
5 NaN 106 NaN NaN David Australia right_only
Stupac `_merge` pokazuje dolazi li red iz oba DataFramea (`both`), samo iz lijevog DataFramea (`left_only`) ili samo iz desnog DataFramea (`right_only`).
Validacija vrsta spajanja
Parametar `validate` osigurava da je operacija spajanja u skladu s očekivanim tipovima odnosa između DataFrameova (npr. 'one_to_one', 'one_to_many'). To pomaže u sprječavanju nedosljednosti podataka i pogrešaka.
Primjer:
# Example with one-to-one validation
df_users = pd.DataFrame({
'user_id': [1, 2, 3],
'username': ['john_doe', 'jane_smith', 'peter_jones']
})
df_profiles = pd.DataFrame({
'user_id': [1, 2, 3],
'profile_description': ['Software Engineer', 'Data Scientist', 'Project Manager']
})
# Performing a one-to-one merge with validation
merged_df = pd.merge(df_users, df_profiles, on='user_id', validate='one_to_one')
print(merged_df)
Ako spajanje krši navedenu validaciju (npr. odnos više-prema-jedan kada je naveden 'jedan-prema-jedan'), bit će podignut `MergeError`, upozoravajući vas na potencijalne probleme s integritetom podataka.
Razmatranja o performansama
Spajanje i pridruživanje DataFrameova može biti računski zahtjevno, posebno za velike skupove podataka. Evo nekoliko savjeta za poboljšanje performansi:
- Koristite odgovarajuću vrstu spajanja: Odabir ispravne vrste spajanja može značajno utjecati na performanse. Na primjer, ako trebate samo podudarne redove, koristite unutarnje spajanje.
- Indeksirajte stupce za spajanje: Indeksiranje stupaca za spajanje može ubrzati proces spajanja.
- Koristite odgovarajuće tipove podataka: Osigurajte da stupci za spajanje imaju kompatibilne tipove podataka.
- Izbjegavajte nepotrebne kopije: Postavite `copy=False` u `pd.merge()` i `df.join()` kako biste izbjegli stvaranje nepotrebnih kopija podataka.
Zaključak
Spajanje i pridruživanje DataFrameova temeljne su operacije u analizi podataka. Razumijevanjem različitih vrsta spajanja i tehnika, možete učinkovito kombinirati i analizirati podatke iz različitih izvora, otključavajući vrijedne uvide i potičući informirano donošenje odluka. Od kombiniranja podataka o prodaji s informacijama o proizvodima do analize globalnih lanaca opskrbe, ovladavanje ovim tehnikama osnažit će vas da se s povjerenjem nosite sa složenim zadacima manipulacije podacima. Ne zaboravite uzeti u obzir implikacije na performanse pri radu s velikim skupovima podataka i iskoristite napredne značajke poput parametara `indicator` i `validate` za robusniju i pronicljiviju analizu.